/*  
 * This file provides the functionality that makes up the UI of the Mashup Editor application.
 * 
 */

mb.editor = {}
mb.editor.formElement = {}
mb.editor.formElement.TEXT_AREA = "TEXT_AREA";
mb.editor.formElement.CHECK_BOX = "CHECK_BOX";


/**
 * @class ParamsTreeNode
 * @extends ObjectTreeNode
 */
var ParamsTreeNode = function(name, type, val, immutable) {
  ParamsTreeNode.superclass.constructor.call(this, name, name, val);
  this.type = type; 
  this.immutable = immutable;
}

jQuery.extend(ParamsTreeNode, ObjectTreeNode, {
  setValue : function(value) {
    if (this.type) {
      value = mb.lang.cast(this.type, value);
    }
    ParamsTreeNode.superclass.setValue.call(this, value);
  }
});


/**
 * @class WidgetMargin
 */
var WidgetMargin = function(el, widget, actionsPanel) {
  this.el = el;
  this.widget = widget;
  this.actionsPanel = actionsPanel || widget.actionsPanel;
  this.el.createChild({ cls : 'af-wgt-margin-line' });
  this.dropTarget = new Ext.dd.DropTarget(this.el, {
    overClass : 'af-wgt-margin-dragover'
  });
  this.dropTarget.addToGroup('BindingObjectDD');
  this.dropTarget.addToGroup('WidgetDD');
  this.dropTarget.addToGroup('UnitActionDD');

  this.dropTarget.notifyEnter = this.handleEnter.createDelegate(this);
  this.dropTarget.notifyOut = this.handleOut.createDelegate(this);
  this.dropTarget.notifyOver = this.handleOver.createDelegate(this);
  this.dropTarget.notifyDrop = this.handleDrop.createDelegate(this);
} 


WidgetMargin.prototype = {
  handleEnter : function(source, event, data) {
    this.mouseInside = true;
    return Ext.dd.DropTarget.prototype.notifyEnter.call(this.dropTarget, source, event, data);
  }
  ,
  handleOut : function(source, event, data) {
    this.mouseInside = false;
    Ext.dd.DropTarget.prototype.notifyOut.call(this.dropTarget, source, event, data);
  }
  ,
  handleOver : function(source, event, data) {
    return "x-dd-drop-ok";
  }
  ,
  handleDrop : function(source, event, data) {
    if (this.mouseInside) {
      window.setTimeout(function() {
        if (source.ddGroup=='BindingObjectDD') {
        } else if (source.ddGroup=='WidgetDD') { 
          this.actionsPanel.insertWidgetAfter(this.widget, data);
        } else if (source.ddGroup=='UnitActionDD') {
          var config = this.actionsPanel.getDefaultActionConfig(data.node.uaction);
          var widget = this.actionsPanel.createActionWidget(config);
          this.actionsPanel.insertWidgetAfter(this.widget, widget);
        } 
      }.createDelegate(this), 100);
    }
    this.dropTarget.notifyOut(source, event, data);
    return true;
  }
}


/**
 * @class ActionInputField
 * @extends Ext.util.Observable
 */
var ActionInputField = function(el, config) {
  this.el = Ext.get(el);
  this.el.addClass('af-actionfield');
  var label = config.label || config.name;
  var form = new Ext.form.Form({ labelWidth : 100 });
  if (config.options) {
    this.control = new SelectBox({
      name : config.name,
      fieldLabel : label,
      editable : true,
      options : config.options,
      width : config.size && config.size == 'large' ? 300 : 150
    });
    if(config.selected)
      this.control.setValue(config.selected, false);
    this.store = this.control.store;
    this.control.on('select', this.handleChange, this);
  } 
  else if (config.formElement == mb.editor.formElement.TEXT_AREA) {
    this.control = new Ext.form.TextArea({
      name : config.name,
      fieldLabel : label,
      selectOnFocus : true,
      grow : !Ext.isSafari // avoiding safari crash
    });
  } 
  else if (config.formElement == mb.editor.formElement.CHECK_BOX) {
    this.control = new Ext.form.Checkbox({
      name : config.name,
      fieldLabel : label
    });
  } 
  else {
    this.control = new Ext.form.TextField({
      name : config.name,
      fieldLabel : label,
      selectOnFocus : true,
      width : config.size && config.size == 'large' ? 300 : 150
    });  
    if(config.invisible)
      this.control.setVisible(false);  
  }
  form.add(this.control);
  form.render(el);

  this.control.on('change', this.handleChange, this);
  //this.control.getEl().on('click', this.handleClick, this);

  this.dropTarget = new Ext.dd.DropTarget(this.control.el, {
    ddGroup : 'BindingObjectDD',
    overClass : 'af-actionfield-bind-dragover'
  }); 
  this.dropTarget.notifyOver = this.handleOver.createDelegate(this);
  this.dropTarget.notifyDrop = this.handleDrop.createDelegate(this);
  this.addEvents({
    'change' : true,
    'destroy' : true
  });
}


Ext.extend(ActionInputField, Ext.util.Observable, {
  handleOver : function(source, event, data) {
    return "x-dd-drop-ok";
  }
  ,
  handleDrop : function(source, event, data) {
    this.setValue('${'+data.node.path+'}');
    this.fireEvent('change');
    this.dropTarget.notifyOut(source, event, data);
    return true;
  }
  ,
  handleClick : function(event) {
    event.stopEvent();
  }
  ,
  handleChange : function() {
    this.fireEvent('change', this);
  }
  ,
  setName : function(name) {
    this.control.name = name;
  }
  ,
  getName : function() {
    return this.control.name;
  }
  ,
  setValue : function(value) {
    this.control.setValue(value);
  }
  ,
  getValue : function() {
    return this.control.getValue();
  }
  ,
  destroy : function() {
    this.control.un('change', this.handleChange);
    this.el.remove();
    this.fireEvent('destroy', this);
  }
});


/**
 * @class DynamicActionInputField
 * @extends ActionInputField
 */
var DynamicActionInputField = function(el) {
  this.el = Ext.get(el);
  this.el.addClass('af-actionfield');
 
  var form = new Ext.form.Form({ labelWidth : 40 });

  this.deleteBtn = new Ext.form.TriggerField({
    width : 10,
    cls : 'af-actionfield-delete',
    triggerClass : 'af-actionfield-delete-btn'
  });
  this.deleteBtn.onTriggerClick = this.destroy.createDelegate(this);
  this.label = new Ext.form.TextField({
    fieldLabel : 'Name',
    selectOnFocus : true,
    width : 140
  });
  this.control = new Ext.form.TextField({
    fieldLabel : 'Value',
    selectOnFocus : true,
    width : 140
  });
  form.column({ hideLabels : true, width : 20 }, this.deleteBtn);
  form.column({ width : 200, style : 'margin-left:10px' }, this.label);
  form.column({ width : 200, style : 'margin-left:10px', clear : true }, this.control);
  form.render(this.el);

  this.label.on('change', this.handleChange, this);
  //this.label.getEl().on('click', this.handleClick, this);

  this.control.on('change', this.handleChange, this);
  //this.control.getEl().on('click', this.handleClick, this);

  this.dropTarget = new Ext.dd.DropTarget(this.control.el, {
    ddGroup : 'BindingObjectDD',
    overClass : 'af-actionfield-bind-dragover'
  }); 
  this.dropTarget.notifyOver = this.handleOver.createDelegate(this);
  this.dropTarget.notifyDrop = this.handleDrop.createDelegate(this);
  this.addEvents({
    'change' : true,
    'destroy' : true
  });
}


jQuery.extend(DynamicActionInputField, ActionInputField, {
  setName : function(value) {
    this.label.setValue(value);
  }
  ,
  getName : function() {
    return this.label.getValue();
  }  
  ,
  destroy : function() {
    this.label.el.un('change', this.handleChange);
    DynamicActionInputField.superclass.destroy.apply(this, arguments);
  }
});


/**
 * @class ProcessActionWidget
 * @extends ActionWidget
 */
var ProcessActionWidget = function(el, config) {
  ProcessActionWidget.superclass.constructor.apply(this, arguments);

  this.outputToolbar.addButton({
    text: 'Open Inner Process',
    cls: 'x-btn-text-icon af-open-inner-proc-btn',
    handler: this.openInnerProcessEditor,
    scope : this
  });

  this.innerProcessPanel = 
    this.processPanel.editorApp.createNewProcPanel(this.actionDef.name, this.processPanel);

  if (config.innerProcessConfig) {
    this.innerProcessPanel.loadConfig(config.innerProcessConfig);
  }
  this.actionDef.setInnerProcess(this.innerProcessPanel.processDef);

  if (this.uaction.innerProcessParams) {
    mb.lang.forEach(
      this.uaction.innerProcessParams, 
      function(innerParam) {
        this.innerProcessPanel.paramsPanel.createNewParam(
          innerParam.name, innerParam.type, null, true);
      },
      this
    );
  }  
} 


jQuery.extend(ProcessActionWidget, ActionWidget, {
  openInnerProcessEditor : function() {
    var zoom = Ext.get(document.body).createChild({ style : 'border:1px solid #6593CF;background: #c3daf9' });
    zoom.setXY(this.el.getXY());
    zoom.setWidth(this.el.getWidth());
    zoom.setHeight(this.el.getHeight());
    zoom.setOpacity(.5);
    zoom.shift({
      xy : this.processPanel.el.getXY(),
      width : this.processPanel.el.getWidth(),
      height : this.processPanel.el.getHeight(),
      duration : .5,
      opacity : .3,
      remove : true,
      callback : this._openInnerProcessEditor.createDelegate(this)
    });
  },
  
  _openInnerProcessEditor : function() { 
    this.processPanel.editorApp.activateProcPanel(this.innerProcessPanel);
    var action = this.processPanel.process.resolveRef(this.actionDef.name);
    action.prepareInnerParams(function(params) {
      mb.lang.forEach(mb.lang.keys(params||{}), function(pname) {
        this.innerProcessPanel.paramsPanel.setParamValue(pname, params[pname]);
      }, this);
    }.createDelegate(this))
  }
});


/**
 * @class WidgetManager
 */
var WidgetManager = mb.lang.defineClass({
  initialize : function() {
    this.widgets = {};
  }
  ,
  register : function(nstype, widgetCls) {
    this.widgets[nstype] = widgetCls;
  }
  ,
  findWidget : function(nstype) {
    return this.widgets[nstype];
  }
});

mb.editor.widgets = new WidgetManager();

mb.editor.MashupBuilder = MashupBuilder;
mb.editor.ActionWidget = ActionWidget;
mb.editor.SelectBox = SelectBox;
mb.editor.ActionInputField = ActionInputField;

